package org.phoenixframework.common.security.filter;

import com.alibaba.fastjson.JSONObject;
import org.phoenixframework.common.security.config.TokenManager;
import org.phoenixframework.common.tools.JacksonUtil;
import org.phoenixframework.common.tools.ResponseUtil;
import org.phoenixframework.common.tools.ResultModel;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @author doublelifeke
 * Email: hautxxxyzjk@163.com
 * DateTime: 2021/5/6 22:04
 * Description:
 */
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {

    private final TokenManager tokenManager;

    private final RedisTemplate redisTemplate;

    public TokenAuthenticationFilter(AuthenticationManager authManager, TokenManager tokenManager, RedisTemplate redisTemplate) {
        super(authManager);
        this.tokenManager = tokenManager;
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
        if (req.getRequestURI().contains("security/login")) {
            chain.doFilter(req, res);
            return;
        }
        UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
        if (authentication != null) {
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } else {
            ResponseUtil.out(res, ResultModel.error());
        }
        chain.doFilter(req, res);
    }

    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        String token = request.getHeader("token");
        if (token != null && !"".equals(token.trim())) {
            String userName = tokenManager.getUsernameByToken(token);
            String authorities = JSONObject.toJSONString(redisTemplate.opsForValue().get(userName));
            List<GrantedAuthority> grantedAuthorities = JSONObject.parseArray(authorities, GrantedAuthority.class);
            return new UsernamePasswordAuthenticationToken(userName, token, grantedAuthorities);
        }
        return null;
    }
}